{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [],
   "source": [
    "import torch\n",
    "import torch.nn as nn\n",
    "import torch.nn.functional as F\n",
    "import torch.optim as optim\n",
    "import torchvision\n",
    "from torchvision import datasets, transforms\n",
    "from torch.utils.data import DataLoader, Dataset\n",
    "import h5py\n",
    "import itertools\n",
    "\n",
    "import numpy as np\n",
    "import matplotlib.pyplot as plt\n",
    "from matplotlib import colors\n",
    "from IPython import display\n",
    "import os\n",
    "from PIL import Image\n",
    "from torch.utils.data.dataset import Dataset\n",
    "from matplotlib.pyplot import imread\n",
    "import glob\n",
    "import os\n",
    "import random\n",
    "import pandas as pd\n",
    "from sklearn.preprocessing import LabelEncoder\n",
    "\n",
    "import torch.nn as nn\n",
    "from torchvision.models import alexnet, vgg16, resnet152, resnet18, vgg19\n",
    "\n",
    "%matplotlib inline\n",
    "\n",
    "import matplotlib.pyplot as plt\n",
    "import math\n",
    "\n",
    "import torch.nn.functional as nnf\n",
    "from torch.utils.data import random_split\n",
    "from torch.optim import SGD \n",
    "from torch.distributions import constraints\n",
    "import torchvision as torchv\n",
    "import torchvision.transforms as torchvt\n",
    "import pickle\n",
    "\n",
    "from sklearn.metrics import classification_report, recall_score, f1_score\n",
    "from sklearn.metrics import confusion_matrix\n",
    "import time"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [],
   "source": [
    "# res_net = resnet18(pretrained=True)\n",
    "# # First we freeze all layers\n",
    "# for param in res_net.parameters():\n",
    "#     param.requires_grad = False # frozen layer\n",
    "\n",
    "class Identity(nn.Module):\n",
    "    def __init__(self):\n",
    "        super(Identity, self).__init__()\n",
    "        \n",
    "    def forward(self, x):\n",
    "        return x\n",
    "\n",
    "# res_net.fc = Identity()\n",
    "# res_net.cuda()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 76,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "ResNet(\n",
       "  (conv1): Conv2d(3, 64, kernel_size=(7, 7), stride=(2, 2), padding=(3, 3), bias=False)\n",
       "  (bn1): BatchNorm2d(64, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)\n",
       "  (relu): ReLU(inplace)\n",
       "  (maxpool): MaxPool2d(kernel_size=3, stride=2, padding=1, dilation=1, ceil_mode=False)\n",
       "  (layer1): Sequential(\n",
       "    (0): BasicBlock(\n",
       "      (conv1): Conv2d(64, 64, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)\n",
       "      (bn1): BatchNorm2d(64, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)\n",
       "      (relu): ReLU(inplace)\n",
       "      (conv2): Conv2d(64, 64, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)\n",
       "      (bn2): BatchNorm2d(64, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)\n",
       "    )\n",
       "    (1): BasicBlock(\n",
       "      (conv1): Conv2d(64, 64, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)\n",
       "      (bn1): BatchNorm2d(64, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)\n",
       "      (relu): ReLU(inplace)\n",
       "      (conv2): Conv2d(64, 64, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)\n",
       "      (bn2): BatchNorm2d(64, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)\n",
       "    )\n",
       "  )\n",
       "  (layer2): Sequential(\n",
       "    (0): BasicBlock(\n",
       "      (conv1): Conv2d(64, 128, kernel_size=(3, 3), stride=(2, 2), padding=(1, 1), bias=False)\n",
       "      (bn1): BatchNorm2d(128, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)\n",
       "      (relu): ReLU(inplace)\n",
       "      (conv2): Conv2d(128, 128, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)\n",
       "      (bn2): BatchNorm2d(128, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)\n",
       "      (downsample): Sequential(\n",
       "        (0): Conv2d(64, 128, kernel_size=(1, 1), stride=(2, 2), bias=False)\n",
       "        (1): BatchNorm2d(128, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)\n",
       "      )\n",
       "    )\n",
       "    (1): BasicBlock(\n",
       "      (conv1): Conv2d(128, 128, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)\n",
       "      (bn1): BatchNorm2d(128, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)\n",
       "      (relu): ReLU(inplace)\n",
       "      (conv2): Conv2d(128, 128, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)\n",
       "      (bn2): BatchNorm2d(128, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)\n",
       "    )\n",
       "  )\n",
       "  (layer3): Sequential(\n",
       "    (0): BasicBlock(\n",
       "      (conv1): Conv2d(128, 256, kernel_size=(3, 3), stride=(2, 2), padding=(1, 1), bias=False)\n",
       "      (bn1): BatchNorm2d(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)\n",
       "      (relu): ReLU(inplace)\n",
       "      (conv2): Conv2d(256, 256, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)\n",
       "      (bn2): BatchNorm2d(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)\n",
       "      (downsample): Sequential(\n",
       "        (0): Conv2d(128, 256, kernel_size=(1, 1), stride=(2, 2), bias=False)\n",
       "        (1): BatchNorm2d(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)\n",
       "      )\n",
       "    )\n",
       "    (1): BasicBlock(\n",
       "      (conv1): Conv2d(256, 256, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)\n",
       "      (bn1): BatchNorm2d(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)\n",
       "      (relu): ReLU(inplace)\n",
       "      (conv2): Conv2d(256, 256, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)\n",
       "      (bn2): BatchNorm2d(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)\n",
       "    )\n",
       "  )\n",
       "  (layer4): Sequential(\n",
       "    (0): BasicBlock(\n",
       "      (conv1): Conv2d(256, 512, kernel_size=(3, 3), stride=(2, 2), padding=(1, 1), bias=False)\n",
       "      (bn1): BatchNorm2d(512, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)\n",
       "      (relu): ReLU(inplace)\n",
       "      (conv2): Conv2d(512, 512, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)\n",
       "      (bn2): BatchNorm2d(512, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)\n",
       "      (downsample): Sequential(\n",
       "        (0): Conv2d(256, 512, kernel_size=(1, 1), stride=(2, 2), bias=False)\n",
       "        (1): BatchNorm2d(512, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)\n",
       "      )\n",
       "    )\n",
       "    (1): BasicBlock(\n",
       "      (conv1): Conv2d(512, 512, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)\n",
       "      (bn1): BatchNorm2d(512, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)\n",
       "      (relu): ReLU(inplace)\n",
       "      (conv2): Conv2d(512, 512, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)\n",
       "      (bn2): BatchNorm2d(512, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)\n",
       "    )\n",
       "  )\n",
       "  (avgpool): AdaptiveAvgPool2d(output_size=(1, 1))\n",
       "  (fc): Identity()\n",
       ")"
      ]
     },
     "execution_count": 76,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "ckpt_gaf = torch.load('res_net_test_recall_best_gaf.chk')\n",
    "res_net_gaf = resnet18(pretrained=True)\n",
    "for param in res_net_gaf.parameters():\n",
    "    param.requires_grad = False\n",
    "\n",
    "num_ftrs = res_net_gaf.fc.in_features\n",
    "res_net_gaf.fc = nn.Sequential(\n",
    "                nn.Linear(in_features=num_ftrs, out_features=256, bias=False),\n",
    "                nn.ReLU(),\n",
    "                nn.Linear(in_features=256, out_features=128, bias=True),\n",
    "                nn.ReLU(),\n",
    "                nn.Linear(in_features=128, out_features=5, bias=True))\n",
    "res_net_gaf.load_state_dict(ckpt_gaf['net'])\n",
    "res_net_gaf.fc = Identity()\n",
    "res_net_gaf.cuda()   "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "ResNet(\n",
       "  (conv1): Conv2d(3, 64, kernel_size=(7, 7), stride=(2, 2), padding=(3, 3), bias=False)\n",
       "  (bn1): BatchNorm2d(64, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)\n",
       "  (relu): ReLU(inplace)\n",
       "  (maxpool): MaxPool2d(kernel_size=3, stride=2, padding=1, dilation=1, ceil_mode=False)\n",
       "  (layer1): Sequential(\n",
       "    (0): BasicBlock(\n",
       "      (conv1): Conv2d(64, 64, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)\n",
       "      (bn1): BatchNorm2d(64, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)\n",
       "      (relu): ReLU(inplace)\n",
       "      (conv2): Conv2d(64, 64, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)\n",
       "      (bn2): BatchNorm2d(64, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)\n",
       "    )\n",
       "    (1): BasicBlock(\n",
       "      (conv1): Conv2d(64, 64, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)\n",
       "      (bn1): BatchNorm2d(64, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)\n",
       "      (relu): ReLU(inplace)\n",
       "      (conv2): Conv2d(64, 64, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)\n",
       "      (bn2): BatchNorm2d(64, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)\n",
       "    )\n",
       "  )\n",
       "  (layer2): Sequential(\n",
       "    (0): BasicBlock(\n",
       "      (conv1): Conv2d(64, 128, kernel_size=(3, 3), stride=(2, 2), padding=(1, 1), bias=False)\n",
       "      (bn1): BatchNorm2d(128, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)\n",
       "      (relu): ReLU(inplace)\n",
       "      (conv2): Conv2d(128, 128, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)\n",
       "      (bn2): BatchNorm2d(128, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)\n",
       "      (downsample): Sequential(\n",
       "        (0): Conv2d(64, 128, kernel_size=(1, 1), stride=(2, 2), bias=False)\n",
       "        (1): BatchNorm2d(128, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)\n",
       "      )\n",
       "    )\n",
       "    (1): BasicBlock(\n",
       "      (conv1): Conv2d(128, 128, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)\n",
       "      (bn1): BatchNorm2d(128, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)\n",
       "      (relu): ReLU(inplace)\n",
       "      (conv2): Conv2d(128, 128, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)\n",
       "      (bn2): BatchNorm2d(128, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)\n",
       "    )\n",
       "  )\n",
       "  (layer3): Sequential(\n",
       "    (0): BasicBlock(\n",
       "      (conv1): Conv2d(128, 256, kernel_size=(3, 3), stride=(2, 2), padding=(1, 1), bias=False)\n",
       "      (bn1): BatchNorm2d(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)\n",
       "      (relu): ReLU(inplace)\n",
       "      (conv2): Conv2d(256, 256, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)\n",
       "      (bn2): BatchNorm2d(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)\n",
       "      (downsample): Sequential(\n",
       "        (0): Conv2d(128, 256, kernel_size=(1, 1), stride=(2, 2), bias=False)\n",
       "        (1): BatchNorm2d(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)\n",
       "      )\n",
       "    )\n",
       "    (1): BasicBlock(\n",
       "      (conv1): Conv2d(256, 256, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)\n",
       "      (bn1): BatchNorm2d(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)\n",
       "      (relu): ReLU(inplace)\n",
       "      (conv2): Conv2d(256, 256, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)\n",
       "      (bn2): BatchNorm2d(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)\n",
       "    )\n",
       "  )\n",
       "  (layer4): Sequential(\n",
       "    (0): BasicBlock(\n",
       "      (conv1): Conv2d(256, 512, kernel_size=(3, 3), stride=(2, 2), padding=(1, 1), bias=False)\n",
       "      (bn1): BatchNorm2d(512, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)\n",
       "      (relu): ReLU(inplace)\n",
       "      (conv2): Conv2d(512, 512, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)\n",
       "      (bn2): BatchNorm2d(512, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)\n",
       "      (downsample): Sequential(\n",
       "        (0): Conv2d(256, 512, kernel_size=(1, 1), stride=(2, 2), bias=False)\n",
       "        (1): BatchNorm2d(512, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)\n",
       "      )\n",
       "    )\n",
       "    (1): BasicBlock(\n",
       "      (conv1): Conv2d(512, 512, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)\n",
       "      (bn1): BatchNorm2d(512, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)\n",
       "      (relu): ReLU(inplace)\n",
       "      (conv2): Conv2d(512, 512, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)\n",
       "      (bn2): BatchNorm2d(512, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)\n",
       "    )\n",
       "  )\n",
       "  (avgpool): AdaptiveAvgPool2d(output_size=(1, 1))\n",
       "  (fc): Identity()\n",
       ")"
      ]
     },
     "execution_count": 4,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "ckpt_rp = torch.load('res_net_test_recall_best_rp.chk')\n",
    "res_net_rp = resnet18(pretrained=True)\n",
    "for param in res_net_rp.parameters():\n",
    "    param.requires_grad = False\n",
    "\n",
    "num_ftrs = res_net_rp.fc.in_features\n",
    "res_net_rp.fc = nn.Sequential(\n",
    "                nn.Linear(in_features=num_ftrs, out_features=256, bias=False),\n",
    "                nn.ReLU(),\n",
    "                nn.Linear(in_features=256, out_features=128, bias=True),\n",
    "                nn.ReLU(),\n",
    "                nn.Linear(in_features=128, out_features=5, bias=True))\n",
    "res_net_rp.load_state_dict(ckpt_rp['net'])\n",
    "res_net_rp.fc = Identity()\n",
    "res_net_rp.cuda()   "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Function for moving tensor or model to GPU\n",
    "def cuda(xs):\n",
    "    if torch.cuda.is_available():\n",
    "        if not isinstance(xs, (list, tuple)):\n",
    "            return xs.cuda()\n",
    "        else:\n",
    "            return [x.cuda() for x in xs]\n",
    "    else:\n",
    "        return xs\n",
    "\n",
    "# Custom class for defining dataset for training with augmentation\n",
    "class Dataset_Hdf5(Dataset):\n",
    "\n",
    "    def __init__(self, path, data_type):\n",
    "        \"\"\" Intialize the dataset\n",
    "        \"\"\"\n",
    "        self.path = path\n",
    "        self.file = h5py.File(path, 'r')\n",
    "        self.images = self.file['x_{}'.format(data_type)]\n",
    "        self.labels = self.file['y_{}'.format(data_type)]\n",
    "                \n",
    "        self.len = self.images.shape[0]\n",
    "        if data_type == 'train':\n",
    "            # no augmentation as we are transforming heartbeats to images via gramian angular field\n",
    "            self.transform = transforms.Compose([\n",
    "#                                               transforms.ToPILImage(),\n",
    "#                                               transforms.RandomRotation((0, 360)),\n",
    "#                                               transforms.RandomHorizontalFlip(),\n",
    "#                                               transforms.RandomVerticalFlip(),\n",
    "                                              transforms.ToTensor()])\n",
    "        else:\n",
    "            self.transform = transforms.Compose([transforms.ToTensor()])\n",
    "\n",
    "    # You must override __getitem__ and __len__\n",
    "    def __getitem__(self, index):\n",
    "        \"\"\" Get a sample from the dataset\n",
    "        \"\"\"\n",
    "        # unsqueeze adds dimension to image -> converts to 1x224x224 since we don't have rgb\n",
    "        return self.transform(self.images[index].astype('float32')), \\\n",
    "                torch.tensor(self.labels[index], dtype=torch.long)\n",
    "\n",
    "    def __len__(self):\n",
    "        \"\"\"\n",
    "        Total number of samples in the dataset\n",
    "        \"\"\"\n",
    "        return self.len"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [],
   "source": [
    "hb_train_loader_bln_3 = torch.utils.data.DataLoader(Dataset_Hdf5('/home/asif/heartbeat/hb_data_mit_bih_balanced_3.hdf5', 'train'), \n",
    "                                                batch_size=512, shuffle=True)\n",
    "hb_test_loader_bln_3 = torch.utils.data.DataLoader(Dataset_Hdf5('/home/asif/heartbeat/hb_data_mit_bih_balanced_3.hdf5', 'test'), \n",
    "                                                batch_size=512, shuffle=False)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [],
   "source": [
    "hb_train_loader_bln_4 = torch.utils.data.DataLoader(Dataset_Hdf5('/home/asif/heartbeat/hb_data_mit_bih_balanced_rp.hdf5', 'train'), \n",
    "                                                batch_size=512, shuffle=False)\n",
    "hb_test_loader_bln_4 = torch.utils.data.DataLoader(Dataset_Hdf5('/home/asif/heartbeat/hb_data_mit_bih_balanced_rp.hdf5', 'test'), \n",
    "                                                batch_size=512, shuffle=False)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "metadata": {},
   "outputs": [],
   "source": [
    "train_size = 0\n",
    "for i, data in enumerate(hb_train_loader_bln_3, 0):\n",
    "    train_size += data[0].shape[0]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "metadata": {},
   "outputs": [],
   "source": [
    "test_size = 0\n",
    "for i, data in enumerate(hb_test_loader_bln_3, 0):\n",
    "    test_size += data[0].shape[0]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [],
   "source": [
    "train_size = 152471\n",
    "test_size = 21892"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(152471, 21892)"
      ]
     },
     "execution_count": 10,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "train_size, test_size"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "152471\n"
     ]
    }
   ],
   "source": [
    "with h5py.File('hb_gaf_bih_intermediate.hdf5', mode='w') as hdf5_file:\n",
    "    hdf5_file.create_dataset(\"x_train\", (train_size, 512), np.float32)\n",
    "    hdf5_file.create_dataset(\"y_train\", (train_size,), np.int32)\n",
    "    hdf5_file.create_dataset(\"x_test\", (test_size, 512), np.float32)\n",
    "    hdf5_file.create_dataset(\"y_test\", (test_size,), np.int32)\n",
    "    \n",
    "    index = 0\n",
    "    for _, data in enumerate(hb_train_loader_bln_3, 0):\n",
    "        inputs, labels = cuda(data)\n",
    "        outputs = res_net(inputs.expand(-1, 3, -1, -1))\n",
    "        hdf5_file[\"x_train\"][index:index + outputs.shape[0], ...] = outputs.cpu().numpy()\n",
    "        hdf5_file[\"y_train\"][index:index + outputs.shape[0]] = labels.cpu().numpy()\n",
    "        index += outputs.shape[0]\n",
    "    print(index)\n",
    "    index = 0\n",
    "    for _, data in enumerate(hb_test_loader_bln_3, 0):\n",
    "        inputs, labels = cuda(data)\n",
    "        outputs = res_net(inputs.expand(-1, 3, -1, -1))\n",
    "        hdf5_file[\"x_test\"][index:index + outputs.shape[0], ...] = outputs.cpu().numpy()\n",
    "        hdf5_file[\"y_test\"][index:index + outputs.shape[0]] = labels.cpu().numpy()\n",
    "        index += outputs.shape[0]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "152471\n",
      "21892\n"
     ]
    }
   ],
   "source": [
    "with h5py.File('hb_rp_bih_intermediate.hdf5', mode='w') as hdf5_file:\n",
    "    hdf5_file.create_dataset(\"x_train\", (train_size, 512), np.float32)\n",
    "    hdf5_file.create_dataset(\"y_train\", (train_size,), np.int32)\n",
    "    hdf5_file.create_dataset(\"x_test\", (test_size, 512), np.float32)\n",
    "    hdf5_file.create_dataset(\"y_test\", (test_size,), np.int32)\n",
    "    \n",
    "    index = 0\n",
    "    for _, data in enumerate(hb_train_loader_bln_4, 0):\n",
    "        inputs, labels = cuda(data)\n",
    "        outputs = res_net(inputs.expand(-1, 3, -1, -1))\n",
    "        hdf5_file[\"x_train\"][index:index + outputs.shape[0], ...] = outputs.cpu().numpy()\n",
    "        hdf5_file[\"y_train\"][index:index + outputs.shape[0]] = labels.cpu().numpy()\n",
    "        index += outputs.shape[0]\n",
    "    print(index)\n",
    "    index = 0\n",
    "    for _, data in enumerate(hb_test_loader_bln_4, 0):\n",
    "        inputs, labels = cuda(data)\n",
    "        outputs = res_net(inputs.expand(-1, 3, -1, -1))\n",
    "        hdf5_file[\"x_test\"][index:index + outputs.shape[0], ...] = outputs.cpu().numpy()\n",
    "        hdf5_file[\"y_test\"][index:index + outputs.shape[0]] = labels.cpu().numpy()\n",
    "        index += outputs.shape[0]\n",
    "    print(index)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "152471\n"
     ]
    }
   ],
   "source": [
    "with h5py.File('hb_gaf_rp_bih_intermediate.hdf5', mode='w') as hdf5_file:\n",
    "    hdf5_file.create_dataset(\"x_train\", (train_size, 1024), np.float32)\n",
    "    hdf5_file.create_dataset(\"y_train\", (train_size,), np.int32)\n",
    "    hdf5_file.create_dataset(\"x_test\", (test_size, 1024), np.float32)\n",
    "    hdf5_file.create_dataset(\"y_test\", (test_size,), np.int32)\n",
    "    \n",
    "    index = 0\n",
    "    for _, (data_gaf, data_rp) in enumerate(zip(hb_train_loader_bln_3, hb_train_loader_bln_4), 0):\n",
    "        inputs_gaf, labels = cuda(data_gaf)\n",
    "        inputs_rp, _ = cuda(data_rp)\n",
    "        outputs_gaf = res_net_gaf(inputs_gaf.expand(-1, 3, -1, -1))\n",
    "        outputs_rp = res_net_rp(inputs_rp.expand(-1, 3, -1, -1))\n",
    "        hdf5_file[\"x_train\"][index:index + outputs_gaf.shape[0], :512] = outputs_gaf.cpu().numpy()\n",
    "        hdf5_file[\"x_train\"][index:index + outputs_rp.shape[0], 512:1024] = outputs_rp.cpu().numpy()\n",
    "        hdf5_file[\"y_train\"][index:index + outputs_gaf.shape[0]] = labels.cpu().numpy()\n",
    "        index += outputs_gaf.shape[0]\n",
    "    print(index)\n",
    "    index = 0\n",
    "    for _, (data_gaf, data_rp) in enumerate(zip(hb_test_loader_bln_3, hb_test_loader_bln_4), 0):\n",
    "        inputs_gaf, labels = cuda(data_gaf)\n",
    "        inputs_rp, _ = cuda(data_rp)\n",
    "        outputs_gaf = res_net_gaf(inputs_gaf.expand(-1, 3, -1, -1))\n",
    "        outputs_rp = res_net_rp(inputs_rp.expand(-1, 3, -1, -1))\n",
    "        hdf5_file[\"x_test\"][index:index + outputs_gaf.shape[0], :512] = outputs_gaf.cpu().numpy()\n",
    "        hdf5_file[\"x_test\"][index:index + outputs_rp.shape[0], 512:1024] = outputs_rp.cpu().numpy()\n",
    "        hdf5_file[\"y_test\"][index:index + outputs_gaf.shape[0]] = labels.cpu().numpy()\n",
    "        index += outputs_gaf.shape[0]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "Sequential(\n",
       "  (0): Linear(in_features=1024, out_features=512, bias=False)\n",
       "  (1): ReLU()\n",
       "  (2): Linear(in_features=512, out_features=256, bias=False)\n",
       "  (3): ReLU()\n",
       "  (4): Linear(in_features=256, out_features=128, bias=True)\n",
       "  (5): ReLU()\n",
       "  (6): Linear(in_features=128, out_features=5, bias=True)\n",
       ")"
      ]
     },
     "execution_count": 7,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "net = nn.Sequential(\n",
    "                nn.Linear(in_features=1024, out_features=512, bias=False),\n",
    "                nn.ReLU(),\n",
    "#                 nn.Dropout(p=0.5),\n",
    "                nn.Linear(in_features=512, out_features=256, bias=False),\n",
    "                nn.ReLU(),\n",
    "                nn.Linear(in_features=256, out_features=128, bias=True),\n",
    "                nn.ReLU(),\n",
    "#                 nn.Dropout(p=0.5),\n",
    "                nn.Linear(in_features=128, out_features=5, bias=True))\n",
    "net.cuda()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Custom class for defining dataset for training with augmentation\n",
    "class DatasetFusion(Dataset):\n",
    "\n",
    "    def __init__(self, path, data_type):\n",
    "        \"\"\" Intialize the dataset\n",
    "        \"\"\"\n",
    "        self.path = path\n",
    "        self.file = h5py.File(path, 'r')\n",
    "        self.images = self.file['x_{}'.format(data_type)]\n",
    "        self.labels = self.file['y_{}'.format(data_type)]\n",
    "                \n",
    "        self.len = self.images.shape[0]\n",
    "        if data_type == 'train':\n",
    "            # no augmentation as we are transforming heartbeats to images via gramian angular field\n",
    "            self.transform = transforms.Compose([\n",
    "\n",
    "                                              transforms.ToTensor()])\n",
    "        else:\n",
    "            self.transform = transforms.Compose([transforms.ToTensor()])\n",
    "\n",
    "    # You must override __getitem__ and __len__\n",
    "    def __getitem__(self, index):\n",
    "        \"\"\" Get a sample from the dataset\n",
    "        \"\"\"\n",
    "        # unsqueeze adds dimension to image -> converts to 1x224x224 since we don't have rgb\n",
    "        return torch.tensor(self.images[index].astype('float32')), \\\n",
    "                torch.tensor(self.labels[index], dtype=torch.long)\n",
    "\n",
    "    def __len__(self):\n",
    "        \"\"\"\n",
    "        Total number of samples in the dataset\n",
    "        \"\"\"\n",
    "        return self.len"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [],
   "source": [
    "hb_train_loader = torch.utils.data.DataLoader(DatasetFusion('/home/asif/heartbeat/hb_gaf_rp_bih_intermediate.hdf5', 'train'), \n",
    "                                                batch_size=512, shuffle=True)\n",
    "hb_test_loader = torch.utils.data.DataLoader(DatasetFusion('/home/asif/heartbeat/hb_gaf_rp_bih_intermediate.hdf5', 'test'), \n",
    "                                                batch_size=512, shuffle=False)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {},
   "outputs": [],
   "source": [
    "class_weights = cuda(torch.tensor([1.0,2.0, 1.0, 2.0, 1.0]))\n",
    "criterion = nn.CrossEntropyLoss(weight=class_weights)\n",
    "# criterion = nn.CrossEntropyLoss()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {},
   "outputs": [],
   "source": [
    "optimizer = torch.optim.Adam([\n",
    "                                          {\"params\": net[0].parameters(), \"lr\": 0.001},\n",
    "                                          {\"params\": net[2].parameters(), \"lr\": 0.001},\n",
    "                                          {\"params\": net[4].parameters(), \"lr\": 0.002},\n",
    "#                                           {\"params\": net[6].parameters(), \"lr\": 0.002},\n",
    "                                           ],\n",
    "                                lr=0.001, betas=(0.5, 0.999))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 69,
   "metadata": {},
   "outputs": [],
   "source": [
    "optimizer_res_net = torch.optim.Adam([\n",
    "                                          {\"params\": res_net_gaf.fc[0].parameters(), \"lr\": 0.001},\n",
    "                                          {\"params\": res_net_gaf.fc[2].parameters(), \"lr\": 0.001},\n",
    "                                          {\"params\": res_net_gaf.fc[4].parameters(), \"lr\": 0.001},\n",
    "                                           ],  \n",
    "                                lr=0.0001, betas=(0.9, 0.999))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {},
   "outputs": [],
   "source": [
    "def train(net, train_loader, criterion, optimizer, test_loader, num_epochs=25):\n",
    "    net.train()\n",
    "    train_acc_max = 0\n",
    "    test_acc_max = 0\n",
    "    recall_max = 0\n",
    "    f1_max = 0\n",
    "\n",
    "#     scheduler = optim.lr_scheduler.ExponentialLR(optimizer, gamma = 0.95)\n",
    "    \n",
    "    \n",
    "    for epoch in range(num_epochs):  # loop over the dataset multiple times\n",
    "        \n",
    "        net.train()\n",
    "\n",
    "        total = 0\n",
    "        correct = 0\n",
    "   \n",
    "        running_loss = 0.0\n",
    "    \n",
    "        for i, data in enumerate(train_loader, 0):\n",
    "            \n",
    "            # get the inputs; data is a list of [inputs, labels]\n",
    "            \n",
    "            inputs, labels = cuda(data)\n",
    "\n",
    "            # zero the parameter gradients\n",
    "            optimizer.zero_grad()\n",
    "\n",
    "            # forward + backward + optimize\n",
    "            outputs = net(inputs) # already in RGB\n",
    "            loss = criterion(outputs, labels)\n",
    "            _, predicted = torch.max(outputs, 1)\n",
    "            total += labels.size(0)\n",
    "            correct += (predicted == labels).sum().item()\n",
    "            \n",
    "            loss.backward()\n",
    "            optimizer.step()\n",
    "\n",
    "            # print statistics\n",
    "            running_loss += loss.item()\n",
    "        \n",
    "#         scheduler.step()\n",
    "        \n",
    "        print('End of epoch {}, Loss {}'.format(epoch + 1, running_loss / len(train_loader)))\n",
    "        \n",
    "        train_acc = correct / total\n",
    "        print('Train accuracy: {}'.format(train_acc))\n",
    "        test_acc, all_true, all_pred = test(net, test_loader)\n",
    "        print('Test accuracy: {}'.format(test_acc))\n",
    "        print(classification_report(all_true, all_pred, target_names=['N', 'S', 'V', 'F', 'Q']))\n",
    "        recall = recall_score(all_true, all_pred, average='macro')\n",
    "        f1 = f1_score(all_true, all_pred, average='macro')\n",
    "        \n",
    "        # Saving best checkpoint based on performance on test data            \n",
    "        if recall > recall_max:\n",
    "            recall_max = recall\n",
    "            save_checkpoint(epoch + 1, net, optimizer, train_acc, test_acc, recall, f1, 'fc_net_fusion', 'test_recall')\n",
    "            \n",
    "        if f1 > f1_max:\n",
    "            f1_max = f1\n",
    "            save_checkpoint(epoch + 1, net, optimizer, train_acc, test_acc, recall, f1, 'fc_net_fusion', 'test_f1')\n",
    "\n",
    "    print('Finished Training')\n",
    "    \n",
    "def test(net, test_loader):\n",
    "    net.eval()\n",
    "    correct = 0\n",
    "    total = 0\n",
    "    all_true = []\n",
    "    all_pred = []\n",
    "    with torch.no_grad():\n",
    "        for i, data in enumerate(test_loader, 0):\n",
    "            inputs, labels = cuda(data)\n",
    "            all_true.extend(labels.cpu().tolist())\n",
    "            outputs = net(inputs)\n",
    "            _, predicted = torch.max(outputs, 1)\n",
    "            all_pred.extend(predicted.cpu().tolist())\n",
    "            total += labels.size(0)\n",
    "            correct += (predicted == labels).sum().item()\n",
    "\n",
    "    acc = correct / total\n",
    "#     print('Accuracy of the network on the images: %d %%' % (100 * acc))\n",
    "    return acc, all_true, all_pred\n",
    "\n",
    "def save_checkpoint(epoch, net, optimizer, train_acc, test_acc, recall, f1, net_name, param):\n",
    "    checkpoint = {\n",
    "        'net': net.state_dict(),\n",
    "        'optimizer': optimizer.state_dict(),\n",
    "        'train_acc': train_acc,\n",
    "        'test_acc': test_acc,\n",
    "        'recall': recall,\n",
    "        'f1': f1\n",
    "    }\n",
    "    torch.save(checkpoint, '{}_{}_best.chk'.format(net_name, param))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "End of epoch 1, Loss 0.764226275652447\n",
      "Train accuracy: 0.7051570462579769\n",
      "Test accuracy: 0.8439612643888178\n",
      "              precision    recall  f1-score   support\n",
      "\n",
      "           N       0.92      0.94      0.93     18118\n",
      "           S       0.17      0.41      0.24       556\n",
      "           V       0.82      0.39      0.53      1448\n",
      "           F       0.16      0.57      0.25       162\n",
      "           Q       0.76      0.31      0.44      1608\n",
      "\n",
      "    accuracy                           0.84     21892\n",
      "   macro avg       0.56      0.52      0.48     21892\n",
      "weighted avg       0.88      0.84      0.85     21892\n",
      "\n",
      "End of epoch 2, Loss 0.4451605366955467\n",
      "Train accuracy: 0.8518210020266149\n",
      "Test accuracy: 0.1346153846153846\n",
      "              precision    recall  f1-score   support\n",
      "\n",
      "           N       0.99      0.12      0.22     18118\n",
      "           S       0.03      1.00      0.06       556\n",
      "           V       0.86      0.04      0.07      1448\n",
      "           F       0.77      0.17      0.27       162\n",
      "           Q       0.43      0.04      0.08      1608\n",
      "\n",
      "    accuracy                           0.13     21892\n",
      "   macro avg       0.61      0.27      0.14     21892\n",
      "weighted avg       0.91      0.13      0.20     21892\n",
      "\n",
      "End of epoch 3, Loss 0.37204822585386715\n",
      "Train accuracy: 0.8707032812797187\n",
      "Test accuracy: 0.9260003654302942\n",
      "              precision    recall  f1-score   support\n",
      "\n",
      "           N       0.97      0.98      0.97     18118\n",
      "           S       0.45      0.82      0.58       556\n",
      "           V       0.74      0.64      0.68      1448\n",
      "           F       0.63      0.52      0.57       162\n",
      "           Q       0.89      0.71      0.79      1608\n",
      "\n",
      "    accuracy                           0.93     21892\n",
      "   macro avg       0.74      0.73      0.72     21892\n",
      "weighted avg       0.93      0.93      0.93     21892\n",
      "\n",
      "End of epoch 4, Loss 0.19733210696820044\n",
      "Train accuracy: 0.9337185431983787\n",
      "Test accuracy: 0.9646902978256897\n",
      "              precision    recall  f1-score   support\n",
      "\n",
      "           N       0.99      0.99      0.99     18118\n",
      "           S       0.79      0.81      0.80       556\n",
      "           V       0.80      0.90      0.85      1448\n",
      "           F       0.70      0.50      0.58       162\n",
      "           Q       0.91      0.87      0.89      1608\n",
      "\n",
      "    accuracy                           0.96     21892\n",
      "   macro avg       0.84      0.81      0.82     21892\n",
      "weighted avg       0.97      0.96      0.96     21892\n",
      "\n",
      "End of epoch 5, Loss 0.16833793182526058\n",
      "Train accuracy: 0.9387096562625024\n",
      "Test accuracy: 0.9726384067239174\n",
      "              precision    recall  f1-score   support\n",
      "\n",
      "           N       0.99      0.99      0.99     18118\n",
      "           S       0.83      0.83      0.83       556\n",
      "           V       0.90      0.89      0.89      1448\n",
      "           F       0.77      0.65      0.71       162\n",
      "           Q       0.93      0.90      0.92      1608\n",
      "\n",
      "    accuracy                           0.97     21892\n",
      "   macro avg       0.88      0.85      0.87     21892\n",
      "weighted avg       0.97      0.97      0.97     21892\n",
      "\n",
      "End of epoch 6, Loss 0.07717075397029219\n",
      "Train accuracy: 0.9742836342648766\n",
      "Test accuracy: 0.9567421889274621\n",
      "              precision    recall  f1-score   support\n",
      "\n",
      "           N       0.99      0.97      0.98     18118\n",
      "           S       0.81      0.80      0.80       556\n",
      "           V       0.83      0.92      0.87      1448\n",
      "           F       0.75      0.73      0.74       162\n",
      "           Q       0.78      0.93      0.85      1608\n",
      "\n",
      "    accuracy                           0.96     21892\n",
      "   macro avg       0.83      0.87      0.85     21892\n",
      "weighted avg       0.96      0.96      0.96     21892\n",
      "\n",
      "End of epoch 7, Loss 0.03870105056167149\n",
      "Train accuracy: 0.9866531996248467\n",
      "Test accuracy: 0.9766581399598027\n",
      "              precision    recall  f1-score   support\n",
      "\n",
      "           N       1.00      0.99      0.99     18118\n",
      "           S       0.91      0.80      0.85       556\n",
      "           V       0.87      0.96      0.91      1448\n",
      "           F       0.90      0.88      0.89       162\n",
      "           Q       0.90      0.95      0.92      1608\n",
      "\n",
      "    accuracy                           0.98     21892\n",
      "   macro avg       0.91      0.92      0.91     21892\n",
      "weighted avg       0.98      0.98      0.98     21892\n",
      "\n",
      "End of epoch 8, Loss 0.28768258129290286\n",
      "Train accuracy: 0.9138852634271435\n",
      "Test accuracy: 0.9242645715329801\n",
      "              precision    recall  f1-score   support\n",
      "\n",
      "           N       0.96      0.98      0.97     18118\n",
      "           S       0.47      0.66      0.55       556\n",
      "           V       0.86      0.67      0.76      1448\n",
      "           F       0.64      0.57      0.60       162\n",
      "           Q       0.81      0.61      0.70      1608\n",
      "\n",
      "    accuracy                           0.92     21892\n",
      "   macro avg       0.75      0.70      0.72     21892\n",
      "weighted avg       0.92      0.92      0.92     21892\n",
      "\n",
      "End of epoch 9, Loss 0.07709713593975409\n",
      "Train accuracy: 0.9741327859068282\n",
      "Test accuracy: 0.9773433217613741\n",
      "              precision    recall  f1-score   support\n",
      "\n",
      "           N       0.99      0.99      0.99     18118\n",
      "           S       0.87      0.81      0.84       556\n",
      "           V       0.92      0.89      0.90      1448\n",
      "           F       0.62      0.85      0.72       162\n",
      "           Q       0.92      0.94      0.93      1608\n",
      "\n",
      "    accuracy                           0.98     21892\n",
      "   macro avg       0.87      0.90      0.88     21892\n",
      "weighted avg       0.98      0.98      0.98     21892\n",
      "\n",
      "End of epoch 10, Loss 0.43788350210212573\n",
      "Train accuracy: 0.8638888706704881\n",
      "Test accuracy: 0.9413941165722638\n",
      "              precision    recall  f1-score   support\n",
      "\n",
      "           N       0.97      0.99      0.98     18118\n",
      "           S       0.68      0.71      0.70       556\n",
      "           V       0.78      0.88      0.83      1448\n",
      "           F       0.24      0.43      0.31       162\n",
      "           Q       0.94      0.64      0.76      1608\n",
      "\n",
      "    accuracy                           0.94     21892\n",
      "   macro avg       0.73      0.73      0.71     21892\n",
      "weighted avg       0.95      0.94      0.94     21892\n",
      "\n",
      "End of epoch 11, Loss 0.07761971688135558\n",
      "Train accuracy: 0.9748083242059146\n",
      "Test accuracy: 0.9748766672757172\n",
      "              precision    recall  f1-score   support\n",
      "\n",
      "           N       0.99      0.99      0.99     18118\n",
      "           S       0.79      0.82      0.80       556\n",
      "           V       0.86      0.94      0.90      1448\n",
      "           F       0.83      0.67      0.74       162\n",
      "           Q       0.97      0.87      0.91      1608\n",
      "\n",
      "    accuracy                           0.97     21892\n",
      "   macro avg       0.89      0.86      0.87     21892\n",
      "weighted avg       0.98      0.97      0.97     21892\n",
      "\n",
      "End of epoch 12, Loss 0.35106692665675343\n",
      "Train accuracy: 0.9056279554800585\n",
      "Test accuracy: 0.967202631098118\n",
      "              precision    recall  f1-score   support\n",
      "\n",
      "           N       0.99      0.99      0.99     18118\n",
      "           S       0.87      0.71      0.78       556\n",
      "           V       0.81      0.93      0.87      1448\n",
      "           F       0.74      0.53      0.62       162\n",
      "           Q       0.88      0.87      0.88      1608\n",
      "\n",
      "    accuracy                           0.97     21892\n",
      "   macro avg       0.86      0.81      0.83     21892\n",
      "weighted avg       0.97      0.97      0.97     21892\n",
      "\n",
      "End of epoch 13, Loss 0.1365672713676905\n",
      "Train accuracy: 0.9822458041201277\n",
      "Test accuracy: 0.0884341311894756\n",
      "              precision    recall  f1-score   support\n",
      "\n",
      "           N       0.00      0.00      0.00     18118\n",
      "           S       0.20      0.05      0.09       556\n",
      "           V       0.24      0.32      0.27      1448\n",
      "           F       0.03      0.05      0.04       162\n",
      "           Q       0.07      0.90      0.14      1608\n",
      "\n",
      "    accuracy                           0.09     21892\n",
      "   macro avg       0.11      0.26      0.11     21892\n",
      "weighted avg       0.03      0.09      0.03     21892\n",
      "\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "/home/asif/anaconda3/envs/pytorch/lib/python3.7/site-packages/sklearn/metrics/_classification.py:1268: UndefinedMetricWarning: Precision and F-score are ill-defined and being set to 0.0 in labels with no predicted samples. Use `zero_division` parameter to control this behavior.\n",
      "  _warn_prf(average, modifier, msg_start, len(result))\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "End of epoch 14, Loss 0.24712461819434725\n",
      "Train accuracy: 0.9104747788103967\n",
      "Test accuracy: 0.9710853279736891\n",
      "              precision    recall  f1-score   support\n",
      "\n",
      "           N       0.99      0.99      0.99     18118\n",
      "           S       0.75      0.83      0.79       556\n",
      "           V       0.85      0.93      0.89      1448\n",
      "           F       0.76      0.58      0.66       162\n",
      "           Q       0.95      0.87      0.91      1608\n",
      "\n",
      "    accuracy                           0.97     21892\n",
      "   macro avg       0.86      0.84      0.85     21892\n",
      "weighted avg       0.97      0.97      0.97     21892\n",
      "\n",
      "End of epoch 15, Loss 0.271583838032046\n",
      "Train accuracy: 0.9229164890372595\n",
      "Test accuracy: 0.9727297642974603\n",
      "              precision    recall  f1-score   support\n",
      "\n",
      "           N       0.99      1.00      0.99     18118\n",
      "           S       0.78      0.77      0.77       556\n",
      "           V       0.92      0.87      0.89      1448\n",
      "           F       0.75      0.66      0.70       162\n",
      "           Q       0.93      0.92      0.92      1608\n",
      "\n",
      "    accuracy                           0.97     21892\n",
      "   macro avg       0.87      0.84      0.86     21892\n",
      "weighted avg       0.97      0.97      0.97     21892\n",
      "\n",
      "End of epoch 16, Loss 0.032032531301722234\n",
      "Train accuracy: 0.9900636842415935\n",
      "Test accuracy: 0.9738717339667459\n",
      "              precision    recall  f1-score   support\n",
      "\n",
      "           N       1.00      0.99      0.99     18118\n",
      "           S       0.80      0.81      0.80       556\n",
      "           V       0.80      0.98      0.88      1448\n",
      "           F       0.93      0.43      0.59       162\n",
      "           Q       0.98      0.86      0.92      1608\n",
      "\n",
      "    accuracy                           0.97     21892\n",
      "   macro avg       0.90      0.82      0.84     21892\n",
      "weighted avg       0.98      0.97      0.97     21892\n",
      "\n",
      "End of epoch 17, Loss 0.019971163160536414\n",
      "Train accuracy: 0.9937693069501742\n",
      "Test accuracy: 0.9783025762835739\n",
      "              precision    recall  f1-score   support\n",
      "\n",
      "           N       1.00      1.00      1.00     18118\n",
      "           S       0.82      0.83      0.82       556\n",
      "           V       0.83      0.98      0.90      1448\n",
      "           F       0.94      0.50      0.65       162\n",
      "           Q       0.99      0.88      0.93      1608\n",
      "\n",
      "    accuracy                           0.98     21892\n",
      "   macro avg       0.92      0.84      0.86     21892\n",
      "weighted avg       0.98      0.98      0.98     21892\n",
      "\n",
      "End of epoch 18, Loss 0.30927174815895575\n",
      "Train accuracy: 0.917105547940264\n",
      "Test accuracy: 0.9590261282660333\n",
      "              precision    recall  f1-score   support\n",
      "\n",
      "           N       0.99      0.97      0.98     18118\n",
      "           S       0.72      0.75      0.73       556\n",
      "           V       0.74      0.92      0.82      1448\n",
      "           F       0.72      0.59      0.65       162\n",
      "           Q       0.94      0.92      0.93      1608\n",
      "\n",
      "    accuracy                           0.96     21892\n",
      "   macro avg       0.82      0.83      0.82     21892\n",
      "weighted avg       0.96      0.96      0.96     21892\n",
      "\n",
      "End of epoch 19, Loss 0.14069157885700065\n",
      "Train accuracy: 0.9560244243167553\n",
      "Test accuracy: 0.9647359766124611\n",
      "              precision    recall  f1-score   support\n",
      "\n",
      "           N       0.99      0.99      0.99     18118\n",
      "           S       0.78      0.76      0.77       556\n",
      "           V       0.78      0.91      0.84      1448\n",
      "           F       0.69      0.48      0.57       162\n",
      "           Q       0.96      0.84      0.89      1608\n",
      "\n",
      "    accuracy                           0.96     21892\n",
      "   macro avg       0.84      0.80      0.81     21892\n",
      "weighted avg       0.97      0.96      0.96     21892\n",
      "\n",
      "End of epoch 20, Loss 0.03127945677671057\n",
      "Train accuracy: 0.9900374497445416\n",
      "Test accuracy: 0.9753334551434314\n",
      "              precision    recall  f1-score   support\n",
      "\n",
      "           N       1.00      0.99      0.99     18118\n",
      "           S       0.85      0.78      0.81       556\n",
      "           V       0.83      0.96      0.89      1448\n",
      "           F       0.71      0.75      0.73       162\n",
      "           Q       0.97      0.93      0.95      1608\n",
      "\n",
      "    accuracy                           0.98     21892\n",
      "   macro avg       0.87      0.88      0.87     21892\n",
      "weighted avg       0.98      0.98      0.98     21892\n",
      "\n",
      "End of epoch 21, Loss 0.018707621080063335\n",
      "Train accuracy: 0.993552872349496\n",
      "Test accuracy: 0.9684359583409464\n",
      "              precision    recall  f1-score   support\n",
      "\n",
      "           N       1.00      0.98      0.99     18118\n",
      "           S       0.54      0.95      0.68       556\n",
      "           V       0.90      0.91      0.91      1448\n",
      "           F       0.91      0.69      0.78       162\n",
      "           Q       0.97      0.90      0.94      1608\n",
      "\n",
      "    accuracy                           0.97     21892\n",
      "   macro avg       0.86      0.88      0.86     21892\n",
      "weighted avg       0.98      0.97      0.97     21892\n",
      "\n",
      "End of epoch 22, Loss 0.01447097759540724\n",
      "Train accuracy: 0.9950482386814542\n",
      "Test accuracy: 0.9845605700712589\n",
      "              precision    recall  f1-score   support\n",
      "\n",
      "           N       1.00      0.99      1.00     18118\n",
      "           S       0.84      0.87      0.85       556\n",
      "           V       0.92      0.96      0.94      1448\n",
      "           F       0.79      0.83      0.81       162\n",
      "           Q       0.98      0.95      0.97      1608\n",
      "\n",
      "    accuracy                           0.98     21892\n",
      "   macro avg       0.91      0.92      0.91     21892\n",
      "weighted avg       0.98      0.98      0.98     21892\n",
      "\n",
      "End of epoch 23, Loss 0.18342132286337398\n",
      "Train accuracy: 0.9508955801431092\n",
      "Test accuracy: 0.9712680431207747\n",
      "              precision    recall  f1-score   support\n",
      "\n",
      "           N       0.99      0.99      0.99     18118\n",
      "           S       0.81      0.73      0.77       556\n",
      "           V       0.78      0.97      0.87      1448\n",
      "           F       0.84      0.75      0.79       162\n",
      "           Q       0.99      0.84      0.91      1608\n",
      "\n",
      "    accuracy                           0.97     21892\n",
      "   macro avg       0.88      0.86      0.87     21892\n",
      "weighted avg       0.97      0.97      0.97     21892\n",
      "\n",
      "End of epoch 24, Loss 0.020505973384028063\n",
      "Train accuracy: 0.9928904512989355\n",
      "Test accuracy: 0.9873469760643158\n",
      "              precision    recall  f1-score   support\n",
      "\n",
      "           N       0.99      1.00      1.00     18118\n",
      "           S       0.94      0.78      0.85       556\n",
      "           V       0.94      0.96      0.95      1448\n",
      "           F       0.91      0.90      0.90       162\n",
      "           Q       0.97      0.96      0.97      1608\n",
      "\n",
      "    accuracy                           0.99     21892\n",
      "   macro avg       0.95      0.92      0.93     21892\n",
      "weighted avg       0.99      0.99      0.99     21892\n",
      "\n",
      "End of epoch 25, Loss 0.2906972059226851\n",
      "Train accuracy: 0.9199323149976061\n",
      "Test accuracy: 0.8742463000182715\n",
      "              precision    recall  f1-score   support\n",
      "\n",
      "           N       0.92      0.96      0.94     18118\n",
      "           S       0.35      0.58      0.44       556\n",
      "           V       0.67      0.37      0.48      1448\n",
      "           F       0.19      0.52      0.28       162\n",
      "           Q       0.95      0.48      0.64      1608\n",
      "\n",
      "    accuracy                           0.87     21892\n",
      "   macro avg       0.62      0.58      0.55     21892\n",
      "weighted avg       0.89      0.87      0.87     21892\n",
      "\n",
      "End of epoch 26, Loss 0.0888679748519805\n",
      "Train accuracy: 0.9663083471610995\n",
      "Test accuracy: 0.9769778914672026\n",
      "              precision    recall  f1-score   support\n",
      "\n",
      "           N       0.99      1.00      0.99     18118\n",
      "           S       0.90      0.78      0.84       556\n",
      "           V       0.86      0.94      0.90      1448\n",
      "           F       0.75      0.78      0.76       162\n",
      "           Q       0.99      0.88      0.93      1608\n",
      "\n",
      "    accuracy                           0.98     21892\n",
      "   macro avg       0.90      0.87      0.88     21892\n",
      "weighted avg       0.98      0.98      0.98     21892\n",
      "\n",
      "End of epoch 27, Loss 0.02566331946259777\n",
      "Train accuracy: 0.9904703189458979\n",
      "Test accuracy: 0.9829161337474877\n",
      "              precision    recall  f1-score   support\n",
      "\n",
      "           N       0.99      1.00      1.00     18118\n",
      "           S       0.88      0.84      0.86       556\n",
      "           V       0.91      0.95      0.93      1448\n",
      "           F       0.74      0.81      0.77       162\n",
      "           Q       0.99      0.93      0.96      1608\n",
      "\n",
      "    accuracy                           0.98     21892\n",
      "   macro avg       0.90      0.90      0.90     21892\n",
      "weighted avg       0.98      0.98      0.98     21892\n",
      "\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "End of epoch 28, Loss 0.01696021671113152\n",
      "Train accuracy: 0.9940316519206931\n",
      "Test accuracy: 0.9862050063950302\n",
      "              precision    recall  f1-score   support\n",
      "\n",
      "           N       1.00      1.00      1.00     18118\n",
      "           S       0.94      0.81      0.87       556\n",
      "           V       0.92      0.96      0.94      1448\n",
      "           F       0.85      0.78      0.81       162\n",
      "           Q       0.97      0.97      0.97      1608\n",
      "\n",
      "    accuracy                           0.99     21892\n",
      "   macro avg       0.94      0.90      0.92     21892\n",
      "weighted avg       0.99      0.99      0.99     21892\n",
      "\n",
      "End of epoch 29, Loss 0.014443835595953934\n",
      "Train accuracy: 0.9945891349830459\n",
      "Test accuracy: 0.9809976247030879\n",
      "              precision    recall  f1-score   support\n",
      "\n",
      "           N       0.99      1.00      1.00     18118\n",
      "           S       0.92      0.76      0.84       556\n",
      "           V       0.90      0.93      0.92      1448\n",
      "           F       0.54      0.79      0.64       162\n",
      "           Q       0.99      0.94      0.96      1608\n",
      "\n",
      "    accuracy                           0.98     21892\n",
      "   macro avg       0.87      0.88      0.87     21892\n",
      "weighted avg       0.98      0.98      0.98     21892\n",
      "\n",
      "End of epoch 30, Loss 0.4733020342455164\n",
      "Train accuracy: 0.8476038066255223\n",
      "Test accuracy: 0.8432760825872465\n",
      "              precision    recall  f1-score   support\n",
      "\n",
      "           N       0.96      0.87      0.91     18118\n",
      "           S       0.25      0.92      0.40       556\n",
      "           V       0.52      0.62      0.56      1448\n",
      "           F       0.27      0.62      0.37       162\n",
      "           Q       0.87      0.75      0.80      1608\n",
      "\n",
      "    accuracy                           0.84     21892\n",
      "   macro avg       0.57      0.75      0.61     21892\n",
      "weighted avg       0.90      0.84      0.86     21892\n",
      "\n",
      "Finished Training\n"
     ]
    }
   ],
   "source": [
    "train(net, hb_train_loader, criterion, optimizer, hb_test_loader, 30)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 87,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "tensor([-0.1094, -0.0180,  0.0353, -0.0687,  0.0714], grad_fn=<SelectBackward>)"
      ]
     },
     "execution_count": 87,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "net(b)[0]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 47,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[1],\n",
       "       [2],\n",
       "       [3]])"
      ]
     },
     "execution_count": 47,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "np.expand_dims(a, 0)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 49,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "torch.Size([3])"
      ]
     },
     "execution_count": 49,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "torch.tensor(np.array([1,2, 3])).shape"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.7.4"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
